package com.quanyan.club.service.impl;

import com.alibaba.fastjson.JSON;
import com.quanyan.api.APIRequest;
import com.quanyan.api.APIResponse;
import com.quanyan.api.enums.AssetsPayReceive;
import com.quanyan.api.enums.AssetsType;
import com.quanyan.assets.request.ReqUserAccumulateModify;
import com.quanyan.assets.service.UserAssetsService;
import com.quanyan.club.constants.ClubConstants;
import com.quanyan.club.entity.db.*;
import com.quanyan.club.entity.vo.resp.task.ActivitySignUpInfo;
import com.quanyan.club.mapper.*;
import com.quanyan.club.service.ClubFirstOrderTaskService;
import com.quanyan.club.service.CppService;
import com.quanyan.common.constants.Constants;
import com.quanyan.common.exception.BizException;
import com.quanyan.common.utils.StringUtil;
import com.quanyan.user.response.RespUserInfoBase;
import com.quanyan.user.serviceFacade.UserServiceFacade;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by zhuo.shi on 2017/2/21.
 */
@Service
public class ClubFirstOrderTaskServiceImpl extends BaseServiceImpl implements ClubFirstOrderTaskService{

    private static Logger logger = LoggerFactory.getLogger(ClubFirstOrderTaskServiceImpl.class);

    @Autowired
    private UserServiceFacade userServiceFacade;
    @Autowired
    private TbClubActivitySettlementMapper clubActivitySettlementMapper;
    @Autowired
    private TbClubActivityMapper clubActivityMapper;
    @Autowired
    private TbClubMapper clubMapper;
    @Autowired
    private ClubEggTaskMapper clubEggTaskMapper;
    @Autowired
    private UserAssetsService userAssetsService;
    @Autowired
    private TbClubTaskMemEggStreamMapper clubTaskMemEggStreamMapper;
    @Autowired
    private TbClubTaskMapper clubTaskMapper;
    @Autowired
    private TbClubMemberMapper clubMemberMapper;
    @Autowired
    private TbClubTaskParameterMapper clubTaskParameterMapper;
    @Autowired
    private TbClubTaskClubEggStreamMapper clubTaskClubEggStreamMapper;
    @Autowired
    private TbSystemParametersMapper systemParametersMapper;
    @Autowired
    private TbClubTaskSummaryLogMapper clubTaskSummaryLogMapper;
    @Autowired
    private CppService cppService;
    @Autowired
    private TbOrderMapper orderMapper;

    /**
     * 获取新用户，新俱乐部判定时间
     * @return
     */
    private Date getNewUserSplitDate(){
        TbSystemParametersExample example = new TbSystemParametersExample();
        example.createCriteria().andParamKeyEqualTo("task.newuser.split.time").andIsEnableEqualTo(1);

        List<TbSystemParameters> parameterses = systemParametersMapper.selectByExample(example);
        if (parameterses == null || parameterses.size() == 0){
            return null;
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            return sdf.parse(parameterses.get(0).getParamValue());
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    private Integer getMinOrderPrice(){
        TbSystemParametersExample example = new TbSystemParametersExample();
        example.createCriteria().andParamKeyEqualTo("task.newuser.min.order.price").andIsEnableEqualTo(1);

        List<TbSystemParameters> parameterses = systemParametersMapper.selectByExample(example);
//        logger.warn("参数：min order price: " + JSON.toJSONString(parameterses));
        if (parameterses == null || parameterses.size() == 0){
            return null;
        }
        try {
            return Integer.valueOf(parameterses.get(0).getParamValue());
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 判断当前俱乐部是否是此俱乐部主席创建的第一个俱乐部
     * @param clubId    俱乐部id
     * @return
     */
    private boolean isNewClub(int clubId){
        TbClub tbClub = clubMapper.selectByPrimaryKey(clubId);
        if (tbClub == null){
            logger.warn("sd: 俱乐部{}不存在", clubId);
            return false;
        }
        int uid = tbClub.getUid();
        if (!isNewUser(uid)){       //俱乐部主席不是新用户
            logger.warn("sd: 用户{}非新用户", uid);
            return false;
        }
        TbClubExample example = new TbClubExample();
        example.createCriteria().andUidEqualTo(uid).andClubTypeLessThanOrEqualTo(4);
        example.setOrderByClause(" create_time asc");
        List<TbClub> clubList = clubMapper.selectByExample(example);
        if (clubList == null || clubList.size() == 0){
            logger.warn("sd: 用户{}，无创建的俱乐部", uid);
            return false;
        }
        TbClub firstClub = clubList.get(0);
        Date splitDate = getNewUserSplitDate();
        if (splitDate == null || firstClub.getCreateTime().before(splitDate)){      //第一个俱乐部的创建时间在xx时间之前，都算老俱乐部
            logger.warn("sd: 俱乐部{}是老俱乐部，创建时间{}，新时间{}", clubId, firstClub.getCreateTime(), splitDate);
            return false;
        }
        if (clubId == firstClub.getId()){     //第一个创建的俱乐部
            logger.warn("sd: 是{}第一个创建的俱乐部{}", uid, clubId);
            return true;
        }
        return false;
    }

    /**
     * 判断是否是xx时间之后新注册的用户
     * @param uid       用户id
     * @return
     */
    private boolean isNewUser(int uid){
        APIResponse<RespUserInfoBase> response = userServiceFacade.queryUserInfo(uid);
        if(response == null || !response.isRet()){
            return false;
        }
        RespUserInfoBase userInfo = response.getData();
        Date splitDate = getNewUserSplitDate();
        if (splitDate != null && userInfo.getRegTime().after(splitDate)){
            return true;
        }
        return false;
    }

    /**
     * 是否是俱乐部成员
     * @param clubId    俱乐部id
     * @param uid       用户id
     * @return
     */
    private boolean isClubMember(int clubId, int uid){
        TbClubMemberExample example = new TbClubMemberExample();
        example.createCriteria()
                .andClubIdEqualTo(clubId)
                .andUidEqualTo(uid)
                .andIsDeleteEqualTo(Constants.IS_DELETE_FALSE);
        return clubMemberMapper.countByExample(example)>0;
    }

    /**
     * 是否是此俱乐部第一个活动结算
     * @param clubId        俱乐部id
     * @param activityId    活动id
     * @return
     */
    private boolean isFirstActivitySettlment(int clubId, int activityId){
        if (!isNewClub(clubId)){
            return false;
        }
        TbClubActivitySettlementExample settlementExample = new TbClubActivitySettlementExample();
        settlementExample.createCriteria().andClubIdEqualTo(clubId);
        int count = clubActivitySettlementMapper.countByExample(settlementExample);
        if (count > 1){
            return false;       //一笔以上结算
        }

        TbClubActivitySettlementExample activityExample = new TbClubActivitySettlementExample();
        activityExample.createCriteria().andClubIdEqualTo(clubId);
        activityExample.setOrderByClause(" create_time asc");
        List<TbClubActivitySettlement> clubActivityList = clubActivitySettlementMapper.selectByExample(activityExample);
        if (clubActivityList == null || clubActivityList.size() == 0){
            return false;
        }
        int firstActivityId = clubActivityList.get(0).getActivityId();
        if (activityId == firstActivityId){
            return true;       //此次结算的活动是此俱乐部发的第一个活动
        }
        return false;
    }

    /**
     * 是否已经领取了首单奖励
     * @param orderUid      领取奖励uid
     * @param taskId        任务id
     * @return
     */
    private boolean isGotFirstOrderAward(int orderUid, int taskId){
        TbClubTaskMemEggStreamExample eggStreamExample = new TbClubTaskMemEggStreamExample();
        eggStreamExample.createCriteria().andMemberUidEqualTo(orderUid).andTaskIdEqualTo(taskId);
        return clubTaskMemEggStreamMapper.countByExample(eggStreamExample)>0;
    }

    /**
     * 获取俱乐部首单奖励任务
     * @param clubType      俱乐部类型
     * @return
     */
    private TbClubTask getClubFirstOrderTask(int clubType){
        List<Integer> taskIds = clubEggTaskMapper.getClubTaskId(2, clubType);       //次任务
        if (taskIds == null || taskIds.size() == 0){
            return null;
        }
        return clubTaskMapper.selectByPrimaryKey(taskIds.get(0));
    }

    /**
     * 获取俱乐部首次任务配置参数
     * @param clubType      俱乐部类型
     * @param taskId        任务id
     * @return
     */
    private TbClubTaskParameter getClubTaskParameter(int clubType, int taskId){
        TbClubTaskParameterExample parameterExample = new TbClubTaskParameterExample();
        parameterExample.createCriteria()
                .andClubTypeEqualTo(clubType).andTaskIdEqualTo(taskId);
        List<TbClubTaskParameter> parameterList = clubTaskParameterMapper.selectByExample(parameterExample);
        if (parameterList == null || parameterList.size() == 0){
            return null;
        }
        return parameterList.get(0);
    }

    /**
     * 是否已经报名过活动
     * @param uid       用户id
     * @return
     */
    private boolean haveSignUpActivity(int uid){
        Integer minPrice = getMinOrderPrice();
        if (minPrice == null){
            minPrice = 15;
        }
        TbOrderExample example = new TbOrderExample();
        example.createCriteria().andOrderUidEqualTo(uid);
//                .andOrderAmountGreaterThanOrEqualTo(new BigDecimal(minPrice));
        return orderMapper.countByExample(example)>1;
    }

    /**
     * 俱乐部首次活动奖励，活动结算完后掉用此方法
     *
     * @param clubId        俱乐部id
     * @param activityId    结算的活动id
     */
    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.NESTED) //新起一个独立事务，如果发放鸟蛋异常，不影响结算的事务回滚
    public void firstOrderAward(int clubId, int activityId){
        logger.warn("sd: 1 开始计算首单奖励");

        TbClubActivityExample exp = new TbClubActivityExample();
        exp.createCriteria().andClubIdEqualTo(clubId).andActivityIdEqualTo(activityId);
        List<TbClubActivity> activities = clubActivityMapper.selectByExample(exp);
        logger.warn("sd: activities={}", JSON.toJSON(activities));

        if (!isFirstActivitySettlment(clubId, activityId)){     //非新用户新俱乐部的第一次活动结算
            logger.warn("sd: 2 非新用户新俱乐部的第一次活动结算，返回。");
            return;
        }

        Integer minOrderPrice = getMinOrderPrice();
        if (minOrderPrice == null || minOrderPrice == 0){
            minOrderPrice = 15; //默认
        }
        logger.warn("----minOrderPrice=" + minOrderPrice);
        //查询出报名人信息，发放鸟蛋
        List<ActivitySignUpInfo> signUpInfos = clubEggTaskMapper.getClubActivitySignUpInfo(clubId, minOrderPrice, activityId);
        if (signUpInfos == null || signUpInfos.size() == 0){
            logger.warn("sd: 俱乐部{}活动{}无报名费超过{}元的报名人，不进行奖励，返回。", clubId, activityId, minOrderPrice);
            return;
        }
        logger.warn("sd: 俱乐部{}活动{}，报名人信息：{}", clubId, activityId, JSON.toJSON(signUpInfos));

        TbClub tbClub = clubMapper.selectByPrimaryKey(clubId);
        if (tbClub == null){
            throw new BizException("俱乐部不存在");
        }
        TbClubTask clubTask = getClubFirstOrderTask(tbClub.getClubType());
        if (clubTask == null){
            throw new BizException("次任务不存在");
        }

        Date now = new Date();
        if (clubTask.getActiveTimeStart() != null && clubTask.getActiveTimeEnd() != null        //任务有效时间
                && !(now.after(clubTask.getActiveTimeStart()) && now.before(clubTask.getMultipleEndTime()))){
            logger.warn("sd: 俱乐部奖励活动已经过期");
            throw new BizException("俱乐部奖励活动已经过期");
        }
        TbClubTaskParameter taskParameter = getClubTaskParameter(tbClub.getClubType(), clubTask.getId());
        if (taskParameter == null){
            logger.warn("sd: 首单奖励任务参数为空");
            throw new BizException("首单奖励任务参数为空！");
        }
        if (isRecord(clubTask.getId(), tbClub.getId())){
            logger.warn("sd: 俱乐部{}已经完成了首次活动奖励或者未获得首次活动奖励，返回。", clubId);
            return;
        }
        //任务是否是多倍奖励
        boolean isMultiple = false;
        Integer multiple = clubTask.getMultiple();
        if (multiple != null){
            if (clubTask.getMultipleStartTime() != null && now.after(clubTask.getMultipleStartTime())
                    && clubTask.getMultipleEndTime() != null && now.before(clubTask.getMultipleEndTime())){
                isMultiple = true;
            }
        }

        int eggForPerMem = taskParameter.getEggForMem();
        int eggForPreClub = taskParameter.getEggForClub();

        Map<Integer, Long> uidEggMap = new HashMap<>();
        logger.warn("sd: signUpInfos.size={}", signUpInfos.size());
        for (ActivitySignUpInfo signUpInfo : signUpInfos){
            Integer orderUid = signUpInfo.getOrderUid();
            String mobile = signUpInfo.getMobile();
            logger.warn("sd: orderUid=" + orderUid);
            if (orderUid == null){
                continue;
            }
            boolean isNewUser = isNewUser(orderUid);
            boolean isClubMember = isClubMember(clubId, orderUid);
            logger.warn("sd: mobile={}, isNewUser={}, isClubMember={}", mobile, isNewUser, isClubMember);
            if (!isClubMember || !isNewUser){       //代报名，非俱乐部成员，非新用户都不能领取奖励
                continue;
            }
            //如果此俱乐部成员新用户, 已经报过活动，或者已经领取过奖励，不再领取奖励
            boolean haveSignUpActivity = haveSignUpActivity(orderUid);
            boolean isGotFirstOrderAward = isGotFirstOrderAward(orderUid, clubTask.getId());
            logger.warn("sd: mobile={}, haveSignUpActivity={}, isGotFirstOrderAward={}", mobile, haveSignUpActivity, isGotFirstOrderAward);
            if (haveSignUpActivity || isGotFirstOrderAward){
                continue;
            }
            if (isMultiple){
                uidEggMap.put(orderUid, (long)eggForPerMem*multiple);
            }else {
                uidEggMap.put(orderUid, (long)eggForPerMem);
            }
        }
        logger.warn("sd: 满足首单奖励条件的用户：{}", JSON.toJSON(uidEggMap));
        if (uidEggMap.isEmpty()){
            logger.warn("无满足条件的用户，不进行奖励发放。");
            //记录次俱乐部未获得首此活动奖励
            recordFirstOrderLog(clubId, clubTask.getId(), taskParameter.getId(), false, 0L, 0L);
            return;
        }

        long eggForClub = isMultiple?((long)eggForPreClub*multiple):eggForPreClub;       //给俱乐部主席的鸟蛋数
        long eggForClubPresident = eggForClub;
        if (uidEggMap.containsKey(tbClub.getUid())){
            eggForClubPresident = uidEggMap.get(tbClub.getUid()) + eggForClubPresident;
        }
        if (isNewUser(tbClub.getUid()) && !isGotFirstOrderAward(tbClub.getUid(), clubTask.getId())) {
            uidEggMap.put(tbClub.getUid(), eggForClubPresident);
        }
        logger.warn("sd: 俱乐部{}首次活动{}奖励：{}", clubId, activityId, uidEggMap);

        APIResponse response = batchGiveOutEggs(uidEggMap, eggForClub, signUpInfos, clubId, activityId, clubTask.getId(), taskParameter.getId());
        if (response == null || !response.isRet()){
            logger.warn("sd: 俱乐部{}活动{}, 发放鸟蛋异常！", clubId, activityId);
            throw new BizException("俱乐部"+clubId+"首次活动"+activityId+"奖励，批量发放鸟蛋异常！");
        }else {
            Set<Integer> uids = uidEggMap.keySet();
            for (Integer uid : uids) {
                cppService.pushClubCommonMsg(tbClub.getLogoUrl(), "恭喜您获得\"" + clubTask.getTaskName() + "\"的" + "奖励" + uidEggMap.get(uid) + "鸟蛋！", Arrays.asList(uid));
            }
        }
        logger.warn("sd: 俱乐部{}活动{}，首单奖励方法执行完毕！", clubId, activityId);
    }

    /**
     * 批量发放鸟蛋给参加活动的俱乐部成员
     *
     * @param uidEggMap     uid和鸟蛋
     * @param signUpInfos   符合发放鸟蛋条件的报名人信息
     * @return
     */
    private APIResponse batchGiveOutEggs(Map<Integer, Long> uidEggMap, long eggForClub, List<ActivitySignUpInfo> signUpInfos,
                                         int clubId, int activityId, int taskId, int parameterId) {
        //发放鸟蛋
        List<ReqUserAccumulateModify> reqUserAccumulateModifies = new ArrayList<>();
        long eggForMem = 0L;
        for (Map.Entry<Integer, Long> entry : uidEggMap.entrySet()) {
            ReqUserAccumulateModify modify = new ReqUserAccumulateModify();
            modify.setUid(entry.getKey());
            long egg = entry.getValue();
            modify.setAccumulate(egg);
            eggForMem += egg;
            modify.setAssetsType(AssetsType.ASSETS_EGGS.id.byteValue());
            modify.setSystemCode(Constants.CLUB_SYSTEM_CODE);
            modify.setBusinessCode(ClubConstants.CLUB_EGG_WEEK_TASK_CODE);
            String nickname = getNickName(entry.getKey(), signUpInfos);
            logger.warn("nk: uid={}, name={} :", entry.getKey(), nickname);
            if (StringUtil.isBlankOrNull(nickname)){
                RespUserInfoBase userInfo = getUserInfoBase(entry.getKey());
                if (userInfo != null) {
                    nickname = userInfo.getNickName();
                }
            }
            logger.warn("nk2: uid={}, name={} :", entry.getKey(), nickname);
            modify.setReceiver(nickname);
            modify.setPayReceive(AssetsPayReceive.SYSTEM.getName());
            modify.setInfo("任务奖励");
            reqUserAccumulateModifies.add(modify);

            //记录发放鸟蛋流水
            TbClubTaskMemEggStream memEggStream = new TbClubTaskMemEggStream();
            memEggStream.setClubId(clubId);
            memEggStream.setMemberUid(entry.getKey());
            memEggStream.setTaskId(taskId);
            memEggStream.setEgg(entry.getValue().intValue());
            memEggStream.setWeek("");
            memEggStream.setActivityIds(JSON.toJSONString(Arrays.asList(activityId)));
            clubTaskMemEggStreamMapper.insertSelective(memEggStream);
        }
        //记录俱乐部领取流水
        TbClubTaskClubEggStream clubEggStream = new TbClubTaskClubEggStream();
        clubEggStream.setWeek("");
        clubEggStream.setTaskId(taskId);
        clubEggStream.setUid(clubMapper.selectByPrimaryKey(clubId).getUid());
        clubEggStream.setClubId(clubId);
        clubEggStream.setEgg((int)eggForClub);
        clubEggStream.setActivityIds(JSON.toJSONString(Arrays.asList(activityId)));
        clubEggStream.setEggForMem((int)eggForMem);
        clubTaskClubEggStreamMapper.insertSelective(clubEggStream);
        //记录获得首次活动奖励日志
        recordFirstOrderLog(clubId, taskId, parameterId, true, eggForClub, eggForMem);

        APIRequest<List<ReqUserAccumulateModify>> apiRequest = new APIRequest<>();
        apiRequest.setData(reqUserAccumulateModifies);
        return userAssetsService.batchModifyEgg(apiRequest);
    }

    private String getNickName(int orderUid, List<ActivitySignUpInfo> signUpInfos){
        for (ActivitySignUpInfo signUpInfo : signUpInfos) {
            if (signUpInfo.getOrderUid() != null && orderUid == signUpInfo.getOrderUid()){
                return signUpInfo.getName();
            }
        }
        return "";
    }

    private void recordFirstOrderLog(int clubId, int taskId, int parameterId, boolean isFinishTask,
                                     long eggForClub, long eggForMem){

        TbClubTaskSummaryLog log = new TbClubTaskSummaryLog();
        log.setClubId(clubId);
        log.setTaskId(taskId);
        log.setWeek("");
        log.setTaskParameterId(parameterId);
        log.setIsFinishTask(isFinishTask);
        if (isFinishTask) {
            log.setIsGotAwards(true);
            log.setGetAwardsTime(new Date());
            log.setMemGetEggs((int)eggForMem);
            log.setClubGetEggs((int)eggForClub);
        }
        log.setActivityCount(1);

        clubTaskSummaryLogMapper.insertSelective(log);
    }

    /**
     * 是否已经完成或者未获得首次活动奖励
     * @param taskId    任务id
     * @param clubId    俱乐部id
     * @return
     */
    private boolean isRecord(int taskId, int clubId){
        TbClubTaskSummaryLogExample example = new TbClubTaskSummaryLogExample();
        example.createCriteria()
                .andTaskIdEqualTo(taskId).andClubIdEqualTo(clubId);
        return clubTaskSummaryLogMapper.countByExample(example) > 0;
    }
}
